package repository

import (
	"context"
	"docker-api/internal/model"
	"fmt"
	"log"
)

type DockerImagesRepository interface {
	List(ctx context.Context) ([]model.DockerImage, error)
	Pull(ctx context.Context, imageName string) error
	Delete(ctx context.Context, imageId string) error
	Import(ctx context.Context, path string) error
	Tag(ctx context.Context, imageId string, newTag string, newName string) error
	// RefreshImages 刷新镜像列表，清空现有数据并插入新数据
	RefreshImages(ctx context.Context, images []model.DockerImage) error
}

func NewDockerImagesRepository(
	r *Repository,
) DockerImagesRepository {
	return &dockerImagesRepository{
		Repository: r,
	}
}

type dockerImagesRepository struct {
	*Repository
}

func (r *dockerImagesRepository) List(ctx context.Context) ([]model.DockerImage, error) {
	var images []model.DockerImage
	result := r.db.WithContext(ctx).Find(&images)
	if result.Error != nil {
		return nil, fmt.Errorf("查询 Docker 文档失败: %w", result.Error)
	}
	return images, nil
}

func (r *dockerImagesRepository) Pull(ctx context.Context, imageName string) error {
	// TODO: 调用 Docker API 拉取镜像
	return nil
}

func (r *dockerImagesRepository) Delete(ctx context.Context, imageId string) error {
	return r.db.Where("id = ?", imageId).Delete(&model.DockerImage{}).Error
}

func (r *dockerImagesRepository) Import(ctx context.Context, path string) error {
	// TODO: 调用 Docker API 导入镜像
	return nil
}

func (r *dockerImagesRepository) Tag(ctx context.Context, imageId string, newTag string, newName string) error {
	// TODO: 调用 Docker API 为镜像打标签
	return r.db.Where("id = ?", imageId).UpdateColumns(map[string]interface{}{
		"tag":  newTag,
		"name": newName,
	}).Error
}

// RefreshImages 刷新镜像列表，清空现有数据并插入新数据
func (r *dockerImagesRepository) RefreshImages(ctx context.Context, images []model.DockerImage) error {
	// 开始事务
	tx := r.db.WithContext(ctx).Begin()
	if tx.Error != nil {
		return fmt.Errorf("开始事务失败: %w", tx.Error)
	}

	// 清空现有数据，GORM v2 为了防止意外的全表删除，要求必须有 WHERE 条件
	if err := tx.Where("1=1").Delete(&model.DockerImage{}).Error; err != nil {
		tx.Rollback()
		return fmt.Errorf("清空镜像数据失败: %w", err)
	}

	// 插入新数据
	if len(images) > 0 {
		log.Printf("准备插入 %d 个新的镜像数据", len(images))

		if err := tx.Create(&images).Error; err != nil {
			tx.Rollback()
			return fmt.Errorf("插入镜像数据失败: %w", err)
		}
	} else {
		log.Printf("没有新的镜像数据需要插入")
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		return fmt.Errorf("提交事务失败: %w", err)
	}

	return nil
}
